/* 
 * File:   ProcesoNotificacionABMArchivos.cpp
 * Author: max
 * 
 * Created on June 21, 2013, 10:53 AM
 */

#include "server_ProcesoNotificacionABMArchivos.h"
#include "common_MutexScopeLocker.h"
#include "common_NotificacionABMConstantes.h"
#include "common_Codec.h"
#include "common_NumeroUtils.h"

using namespace TP;
using namespace TP::Procesos;
using namespace TP::Servicios;

ProcesoNotificacionABMArchivos::ProcesoNotificacionABMArchivos(const uint32_t &pId, IAdministradorSesiones* pAdministradorSesiones, IAdministradorRepositorioCentral* pAdmRepositorioCentral) : Proceso(pId){
    _admRepositorioCentral = pAdmRepositorioCentral;
    _administradorSesiones = pAdministradorSesiones;
}

ProcesoNotificacionABMArchivos::~ProcesoNotificacionABMArchivos() {
    _admRepositorioCentral = NULL;
    _administradorSesiones = NULL;
}

void ProcesoNotificacionABMArchivos::tarea(){
    
    /* Itera los repositorios del repositorio central en busca de archivos
     * en estado de alta, baja o modificacion a fin de notificar al cliente
     * correspondiente el estado del archivo.
     * 
     */
    while (this->GetCorriendo())
    {
        this->NotificarEventos ();
    }
}

void ProcesoNotificacionABMArchivos::NotificarEventos(){
    
    Sesion* sesion = _administradorSesiones->getSesionPrimera();
    
    while (NULL != sesion)
    {
        Repositorio* repositorio = this->_admRepositorioCentral->GetRepositorioPorIdentificador(sesion->GetUsuario());
        this->NotificarEventosDelRepositorio(sesion, repositorio);
        
        sesion = _administradorSesiones->getSesionSiguiente(sesion);
    }
}

void ProcesoNotificacionABMArchivos::NotificarEventosDelRepositorio (Sesion* pSesion, Repositorio* pRepositorio){
    
    if (NULL != pSesion && NULL != pRepositorio)
    {
        this->NotificarEventosArchivosNuevos (pSesion, pRepositorio);
        this->NotificarEventosArchivosEliminados(pSesion, pRepositorio);
        this->NotificarEventosArchivosModificados (pSesion, pRepositorio);
    }
}

void ProcesoNotificacionABMArchivos::NotificarEventosArchivosNuevos (Sesion* pSesion, Repositorio* pRepositorio){

    /* Itero el repositorio en busca de archivos en estado ARCHIVO_CARGADO. 
     */

    RepoItem* item = pRepositorio->Primero();
    while (NULL != item)
    {
        if (item->GetEstado() == ARCHIVO_CARGADO)
        {
            try
            {
                /* Formato del mensaje:
                 * 
                 * <id_evento>;<nombre_archivo>;<version_archivo>
                 * 
                 */
                string mensaje = NotificacionABMConstantes::NOTIFICACION_NUEVO_ARCHIVO;
                mensaje += SEPARADOR_CAMPO;
                mensaje += Codec::codificar(item->GetFilename());
                mensaje += SEPARADOR_CAMPO;
                mensaje += NumeroUtils::UInt32AString(item->GetVersion());

                pSesion->Responder(mensaje);

                item->SetEstado(ARCHIVO_SINCRONIZADO);
            }
            catch (Excepcion &ex)
            {
                cerr << "Error de notificacion de alta de archivo al cliente. " << ex.what() << endl;
            }
        }
        
        item = pRepositorio->Siguiente(item);
    }
}

void ProcesoNotificacionABMArchivos::NotificarEventosArchivosEliminados(Sesion* pSesion, Repositorio* pRepositorio){

    /* Itero el repositorio en busca de archivos en estado ARCHIVO_BORRADO;
     */

    RepoItem* item = pRepositorio->Primero();
    while (NULL != item)
    {
        if (item->GetEstado() == ARCHIVO_BORRADO)
        {
            try
            {
                /* Formato del mensaje:
                 * 
                 * <id_evento>;<nombre_archivo>;<version_archivo>
                 * 
                 */
                string mensaje = NotificacionABMConstantes::NOTIFICACION_ARCHIVO_BORRADO;
                mensaje += SEPARADOR_CAMPO;
                mensaje += Codec::codificar(item->GetFilename());
                mensaje += SEPARADOR_CAMPO;
                mensaje += NumeroUtils::UInt32AString(item->GetVersion());

                pSesion->Responder(mensaje);
                
                RepoItem* itemAEliminar = item;
                item = pRepositorio->Siguiente(item);
                pRepositorio->RemoverRepoItem(item);
                delete item;
            }
            catch (Excepcion &ex)
            {
                cerr << "Error de notificacion de alta de archivo al cliente. " << ex.what() << endl;
            }
        }
        
        item = pRepositorio->Siguiente(item);
    }    
}

void ProcesoNotificacionABMArchivos::NotificarEventosArchivosModificados (Sesion* pSesion, Repositorio* pRepositorio){
    /* Itero el repositorio en busca de archivos en estado ARCHIVO_MODIFICADO
     */
}

